#ifndef BLOCK_QUEUE_H_
#define BLOCK_QUEUE_H_ 1
#include <condition_variable>
#include <deque>
#include <mutex>
//使用 c++11 中的生产者/消费者模型、锁、unique_ptr、dequeue(双端队列)
//类中 使用 dequeue 为数据模型,存放待写入的 日志信息,以便同步/异步写入
//封装的 dequeue 仅提供 pop_front 不提供 pop_back
template<class T>
class BlockQueue
{
public:
    BlockQueue(size_t maxsize = 1024);
    ~BlockQueue();

    T back();
    T front();

    size_t size();
    size_t capacity();

    void push_front(const T& item);
    void push_back(const T& item);
    void clear();
    void wake();
    void close();
    
    bool pop(T&item);
    bool pop(T&item,int timeout);
    bool empty();
    bool full();


private:
    std::deque<T> deq_;
    size_t maxcapacity;
    bool isClose;
    std::mutex mutex_;
    std::condition_variable Producter;
    std::condition_variable Consumer;
};
template<class T>
BlockQueue<T>::BlockQueue(size_t maxsize)
    :maxcapacity(maxsize),isClose(false)
{
    assert(maxsize>0);
}
template<class T>
T BlockQueue<T>::front()
{
    std::lock_guard<std::mutex> mtx(mutex_);
    return deq_.front();
}
template<class T>
T BlockQueue<T>::back()
{
    std::lock_guard<std::mutex> mtx(mutex_);
    return deq_.back();
}
template<class T>
size_t BlockQueue<T>::size()
{
    std::lock_guard<std::mutex> mtx(mutex_);
    return deq_.size();
}
template<class T>
size_t BlockQueue<T>::capacity()
{
    std::lock_guard<std::mutex> mtx(mutex_);
    return maxcapacity;
}
template<class T>
void BlockQueue<T>::push_front(const T& item)
{
    std::unique_lock<std::mutex> mtx(mutex_);
    while(deq_.size() >=maxcapacity)
    {
        Producter.wait(mtx);
    }
    //dequeue 有空闲空间了
    deq_.push_front(item);
    Consumer.notify_one();
}
template<class T>
void BlockQueue<T>::push_back(const T& item)
{
    std::unique_lock<std::mutex> mtx(mutex_);
    while(deq_.size() >= maxcapacity)
    {
        Producter.wait(mtx);
    }
    //dequeue 有1个空闲空间了，放入一个任务
    deq_.push_back(item);
    Consumer.notify_one();
}
template<class T>
void BlockQueue<T>::clear()
{
    std::lock_guard<std::mutex> mtx(mutex_);
    deq_.clear();
}
template<class T>
bool BlockQueue<T>::pop(T&item)
{
    std::unique_lock<std::mutex> mtx(mutex_);
    while(deq_.empty())
    {
        Consumer.wait(mtx);
    }
    //dequeue 不为空了,取走一个任务
    item = deq_.front();
    deq_.pop_front();
    Producter.notify_one();
    return true;
}
template<class T>
bool BlockQueue<T>::pop(T&item,int timeout_sec)
{
    std::unique_lock<std::mutex> mtx(mutex_);
    while(deq_.empty())
    {
        if(Consumer.wait_for(mtx,std::chrono::seconds(timeout_sec)) 
            == std::cv_status::timeout)
        {
            //超时返回
            return false;
        }
        //没有超时，但因为阻塞队列关闭了
        if(isClose)
        {
            return false;
        }
    }
    //dequeue 不为空了,取走一个任务
    item = deq_.front();
    deq_.pop();
    Producter.notify_one();
    return true;
}
template<class T>
bool BlockQueue<T>::empty()
{
   std::lock_guard<std::mutex> mtx(mutex_);
   return deq_.empty(); 
}
template<class T>
bool BlockQueue<T>::full()
{
    std::lock_guard<std::mutex> mtx(mutex_);
    return deq_.size()>=maxcapacity?1:0;
}
template<class T>
void BlockQueue<T>::wake()
{
    Consumer.notify_one();
}
template<class T>
void BlockQueue<T>::close()
{
    //std::lock_guard<std::mutex> mtx(mutex_);
    clear();
    isClose = true;
    Producter.notify_all();
    Consumer.notify_all();
}
template<class T>
BlockQueue<T>::~BlockQueue()
{
    close();
}
#endif
